#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QInputDialog>
#include <QMessageBox>
#include <QTextStream>
#include <QDebug>
#include <iostream>
#include <string>
#include <list>
#include <algorithm>

using namespace std;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

class Patron;	// 提前声明

// 书类
class Book {
public:
    Book() {
        patron = nullptr;
    }
    bool operator==(const Book& bk) const {
        return title == bk.title;
    }
//private:
    QString title;   // 书名
    Patron* patron;  // 借书人
    // 不选择重载 << 打印所有书籍，而是在后续进行QString字符串处理
//    QTextStream& printBook(QTextStream&) const;
//    friend QTextStream& operator<<(QTextStream& out, const Book& bk) {
//        bk.printBook(out);
//        return out;
//    }
    friend class CheckedOutBook;
    friend Patron;
    friend void includeBook(QString i, QString j);
    friend bool checkOutBook(QString in1, QString in2, QString in3);
    friend bool returnBook(QString in1, QString in2, QString in3);
};

// 作者类
class Author {
public:
    Author() {}
    bool operator== (const Author& ar) const {
        return name == ar.name;   // 重载==，比较两个Author字符串/作者名是否相等/相同
    }
//private:
    QString name;   // 作者名
    QList<Book> books;  // 作者所写书籍
    // 不选择重载 << 打印所有作者，而是在后续进行QString字符串处理
//    QTextStream& printAuthor(QTextStream&) const;
//    friend QTextStream& operator<< (QTextStream& out, const Author& ar) {
//        return ar.printAuthor(out);
//    }
    friend class CheckedOutBook;
    friend Patron;
    friend void includeBook(QString i, QString j);
    friend bool checkOutBook(QString in1, QString in2, QString in3);
    friend bool returnBook(QString in1, QString in2, QString in3);
};

// 被借出的书籍类，其中包括作者和书籍的信息
class CheckedOutBook {
public:
    CheckedOutBook(QList<Author>::iterator ar,
        QList<Book>::iterator bk = QList<Book>::iterator()) {
        author = ar;
        book = bk;
    }
    bool operator==(const CheckedOutBook& bk) const {
        return author->name == bk.author->name &&
               book->title == bk.book->title;
    }
//private:
    QList<Author>::iterator author; // 所有借出的书的作者
    QList<Book>::iterator book;    // 所有借出的书
    friend bool checkOutBook(QString in1, QString in2, QString in3);
    friend bool returnBook(QString in1, QString in2, QString in3);
    friend class Patron;
};


// 顾客类，来借书的人
class Patron {
public:
    Patron() {}
    bool operator==(const Patron& pn) const {
        return name == pn.name;
    }

//private:
    QString name;  // 人名
    QList<CheckedOutBook> books;  // 当前人借的所有书
    // 不选择重载 << 打印所有顾客，而是在后续进行QString字符串处理
//    QTextStream& printPatron(QTextStream&) const;
//    friend QTextStream& operator<< (QTextStream& out, const Patron& pn) {
//        return pn.printPatron(out);
//    }

    friend bool checkOutBook(QString in1, QString in2, QString in3);
    friend bool returnBook(QString in1, QString in2, QString in3);
    friend class Book;
};

// 作者和顾客人名的开头索引
QList<Author> catalog['Z' + 1];
QList<Patron> people['Z' + 1];

QList<Author> authors;
QList<Patron> peoples;

// 1.添加书
void includeBook(QString name, QString book) {
    Author newAuthor;
    Book newBook;
    newAuthor.name = name.toUpper();
    newBook.title = book.toUpper();
    // 在原有作者中，以新作者名字开头首字母作为起始点进行迭代，查找有没有出现过
    QList<Author>::iterator oldAuthor = find(catalog[newAuthor.name[0].toLatin1()].begin(),
                     catalog[newAuthor.name[0].toLatin1()].end(), newAuthor);
    // 新的作者出现（因为迭代完都没找到此人）
    if (oldAuthor == catalog[newAuthor.name[0].toLatin1()].end()) {
        newAuthor.books.push_front(newBook);   // 作者的书籍链表加入该书
        qDebug() << "add book ";
        catalog[newAuthor.name[0].toLatin1()].push_front(newAuthor);  // 作者名加入索引链表
    }
    // 原有作者的新书
    else (*oldAuthor).books.push_front(newBook);
}

// 2.借出书
bool checkOutBook(QString in1, QString in2, QString in3) {
    Patron patron;  // 借书人
    Author author;  // 要借的书的作者
    Book book;      // 要借的书的名
    QList<Author>::iterator authorRef;
    QList<Book>::iterator bookRef;

    // 获取借书人名字
    patron.name = in1.toUpper();

    // 获取作者名
    author.name = in2.toUpper();
    if (author.name.isEmpty()) {
        // 用户点击了 Cancel
        qDebug() << "用户取消了输入作者名 ";
    }
    // 遍历作者list
    authorRef = find(catalog[author.name[0].toLatin1()].begin(),
        catalog[author.name[0].toLatin1()].end(), author);
    // list中找不到作者说明拼错，弹出提示框并返回false
    if (authorRef == catalog[author.name[0].toLatin1()].end()){
        QMessageBox::warning(nullptr, "错误", "拼错作者name", QMessageBox::Ok);
        return false;
    }

    // 获取书名
    book.title = in3.toUpper();
    if (book.title.isEmpty()) {
        // 用户点击了 Cancel
        qDebug() << "用户取消了输入书名 ";
    }
    // 遍历书list
    bookRef = find((*authorRef).books.begin(),
        (*authorRef).books.end(), book);
    // list中找不到书籍说明拼错，弹出提示框并返回false
    if (bookRef == (*authorRef).books.end()){
        QMessageBox::warning(nullptr, "错误", "拼错书籍name", QMessageBox::Ok);
        return false;
    }

    // 在该名借书人上，添加借书的书名和作者名
    QList<Patron>::iterator patronRef;

    // 遍历原有借书人list
    patronRef = find(people[patron.name[0].toLatin1()].begin(),
        people[patron.name[0].toLatin1()].end(), patron);
    CheckedOutBook checkedOutBook(authorRef, bookRef);
    // 没找到，说明是新顾客，需要先加到列表patronRef中
    if (patronRef == people[patron.name[0].toLatin1()].end()) {
        patron.books.push_front(checkedOutBook);
        people[patron.name[0].toLatin1()].push_front(patron);
        (*bookRef).patron = &*people[patron.name[0].toLatin1()].begin();
    }
    // 找到了，说明是老顾客，直接加到book列表里，书也储存被借的人的信息
    else {
        (*patronRef).books.push_front(checkedOutBook);
        (*bookRef).patron = &*patronRef;
    }
    // 借书成功，返回true
    return true;
}

// 3.归还书
bool returnBook(QString in1, QString in2, QString in3) {
    Patron patron;
    Book book;
    Author author;
    QList<Patron>::iterator patronRef;
    QList<Book>::iterator bookRef;
    QList<Author>::iterator authorRef;

    // 下面三种遍历都是查找是否存在顾客/作者/书名，迭代器迭代到末尾都没找到，说明拼错单词，查无此记录
    // 拼错单词/无记录会弹出提示信息并返回false，否则修改好list里的数据，还书成功返回true
    patron.name = in1.toUpper();
    patronRef = find(people[patron.name[0].toLatin1()].begin(),
        people[patron.name[0].toLatin1()].end(), patron);
    if (patronRef == people[patron.name[0].toLatin1()].end()){
        QMessageBox::warning(nullptr, "错误", "拼错顾客name ", QMessageBox::Ok);
        return false;
    }

    author.name = in2.toUpper();
    authorRef = find(catalog[author.name[0].toLatin1()].begin(),
        catalog[author.name[0].toLatin1()].end(), author);
    if (authorRef == catalog[author.name[0].toLatin1()].end()){
        QMessageBox::warning(nullptr, "错误", "拼错作者name ", QMessageBox::Ok);
        return false;
    }

    book.title = in3.toUpper();
    bookRef = find((*authorRef).books.begin(),
        (*authorRef).books.end(), book);
    if (bookRef == (*authorRef).books.end()){
        QMessageBox::warning(nullptr, "错误", "拼错书籍name", QMessageBox::Ok);
        return false;
    }

    CheckedOutBook checkedOutBook(authorRef, bookRef);
    (*bookRef).patron = nullptr;  // 指向nullptr，说明此时书已归还，没人借此书了
    (*patronRef).books.removeOne(checkedOutBook);   // 顾客所指向的，自己的books列表中，将该书删除
    // 还书成功，返回true
    return true;
}

// 4. 当前状态
void status() {
    // 先清空初始化
    authors.clear();
    peoples.clear();
    int i;
    qDebug() << "进入 status 函数 ";
    for (i = 'A'; i <= 'Z'; i++){
        if (!catalog[i].empty()){   // 该字母开头的可能有多本书
            for (const auto& author : catalog[i]) {
                // out << author; // Assuming you have the << operator overloaded for Author
                // 不重载了，而是将author存储到authors数组里
                authors.append(author);
            }
        }
    }
    qDebug() << "第一个循环结束 ";
    for (i = 'A'; i <= 'Z'; i++){
        if (!people[i].empty()){
            for (const auto& person : people[i]) {
                // out << person; // Assuming you have the << operator overloaded for Author
                // 不重载了，而是将person存储到peoples数组里
                peoples.append(person);
            }
        }
    }
    qDebug() << "第二个循环结束 ";
    qDebug() << "退出 status 函数 ";
}



// 添加书和作者
void MainWindow::on_add_clicked()
{
    bool ok;
    QString input1 = QInputDialog::getText(nullptr, "Dialog ", "Enter author's name: ", QLineEdit::Normal, "", &ok);
    if (ok) {
        QString input2 = QInputDialog::getText(this, "Dialog ", "Enter the title of the book: ", QLineEdit::Normal, "", &ok);
        if (ok) {
            // 用户点击了确定按钮，并成功输入了两个值 input1 和 input2，将其作为参数传入该功能的函数中
            includeBook(input1, input2);
            QMessageBox::information(this, "结果 ", "successfully add!\nnewAuthor:  " + input1 + "\nnewBook:  " + input2);
        } else {
            // 用户点击了取消按钮或者关闭了对话框
            QMessageBox::information(this, "结果 ", "user canceled ");
        }
    }

}

void MainWindow::on_lend_clicked()
{
    bool ok;
    QString input1 = QInputDialog::getText(this, "Dialog ", "Enter your name: ", QLineEdit::Normal, "", &ok);

    if (ok) {
        QString input2 = QInputDialog::getText(this, "Dialog ", "Enter author name: ", QLineEdit::Normal, "", &ok);

        if (ok) {
            QString input3 = QInputDialog::getText(this, "Dialog ", "Enter the title of the book: ", QLineEdit::Normal, "", &ok);
            // 用户点击了确定按钮，在这里处理输入的三个值
            if(checkOutBook(input1, input2, input3))
                QMessageBox::information(this, "结果 ", "successfully lend book!\npatron:  " + input1 + "\nlend author:  " + input2 + "\nlend book:  " + input3);
        } else {
            // 用户点击了取消按钮或者关闭了对话框
            QMessageBox::information(this, "结果 ", "user canceled ");
        }
    }
//    checkOutBook();   // 借出书
}

void MainWindow::on_returnbook_clicked()
{
    bool ok;
    QString input1 = QInputDialog::getText(this, "Dialog ", "Enter your name: ", QLineEdit::Normal, "", &ok);

    if (ok) {
        QString input2 = QInputDialog::getText(this, "Dialog ", "Enter author name: ", QLineEdit::Normal, "", &ok);

        if (ok) {
            QString input3 = QInputDialog::getText(this, "Dialog ", "Enter the title of the book: ", QLineEdit::Normal, "", &ok);
            // 用户点击了确定按钮，在这里将输入的三个值传入到归还书的函数returnBook中，进行判断和修改list等操作
            if(returnBook(input1, input2, input3))
                QMessageBox::information(this, "结果 ", "successfully return book!\npatron:  " + input1 + "\nreturn author:  " + input2 + "\nreturn book:  " + input3);
        } else {
            // 用户点击了取消按钮或者关闭了对话框
            QMessageBox::information(this, "结果 ", "user canceled ");
        }
    }
}

void MainWindow::on_status_clicked()
{
    status();         // 图书馆状态
    qDebug() << "status finished ! ";
    QString authorstr = "";
    for (const auto& author : authors) {
        // out << author; // Assuming you have the << operator overloaded for Author
        // 不重载<<了，而是将author存储到authors数组里，并在下面对每个author进行具体字符串拼接操作
        authorstr += author.name + "\n";  // 处理作者的名字
        for (const auto& book : author.books) {
            authorstr += "* " + book.title;  // 处理作者的书籍
            if (book.patron != nullptr) {
                authorstr += " - checked out to " + book.patron->name;
            }
            authorstr += "\n";
        }
    }
    qDebug() << "one for finished ! ";
    QString peoplestr = "";
    for (const auto& people : peoples) {
        // out << author; // Assuming you have the << operator overloaded for Author
        // 不重载<<了，而是将每个people对象都进行对象具体访问，进行字符串的具体拼接操作
        peoplestr += people.name;
        qDebug() << "two 1? ";
        if (!people.books.isEmpty()) {
            peoplestr += " has the following books:\n";
            qDebug() << "two 2? ";
            for (const auto& checkedOutBook : people.books) {
                qDebug() << "two nei? ";
                if (checkedOutBook.author->name != nullptr && checkedOutBook.book->title != nullptr) {
                    // 处理指针的逻辑
                    qDebug() << "People books size: " << people.books.size();
                    qDebug() << "checkedOutBook.author->name: " << checkedOutBook.author->name;
                    qDebug() << "checkedOutBook.book->title: " << checkedOutBook.book->title;
                    peoplestr += QString("* %1,%2\n")
                                     .arg(checkedOutBook.author->name)
                                     .arg(checkedOutBook.book->title);
                    qDebug() << "People books size: " << people.books.size();
                }
            }
        } else {
            peoplestr += " has no books\n";
        }
    }
    qDebug() << "two for finished ! ";
    ui->showAuthors->setPlainText(authorstr);
    ui->showPeoples->setPlainText(peoplestr);
    qDebug() << authorstr;
    qDebug() << peoplestr;
}

void MainWindow::on_help_clicked()
{
    QMessageBox msgBox;
    msgBox.setWindowTitle("tips");
    msgBox.setText("------show infomation------  <br><br> author <br> * the author book1 "
                   "<br>  * the author book2(may be lend) <br> <br> patron1 <br> -patron' books(have following books)"
                   "<br> -book1 book2 <br> patron2 <br> -patron' books(no book) ");
    msgBox.setIcon(QMessageBox::Information);
    msgBox.exec();
}

void MainWindow::on_exit_clicked()
{
    close();          // 退出程序
}






















//QTextStream& Author::printAuthor(QTextStream& out) const {
//    out << name.toUtf8().constData() << endl;
//    QList<Book>::const_iterator ref = books.begin();
//    for (; ref != books.end(); ref++)
//        out << *ref; // overloaded <<
//    return out;
//}

//QTextStream& Book::printBook(QTextStream& out) const {
//    out << "* " << title;
//    if (patron != 0)
//        out << " - checked out to " << patron->name; // overloaded <<
//    out << "\n";
//    return out;
//}

//QTextStream& Patron::printPatron(QTextStream& out) const {
//    out << name;
//    if (!books.empty()) {
//        out << " has the following books:\n";
//        QList<CheckedOutBook>::const_iterator bk = books.begin();
//        for (; bk != books.end(); bk++)
//            out << "*" << bk->author->name << ","
//            << bk->book->title << endl;
//    }
//    else out << " has no books\n";
//    return out;
//}

//template<class T>
//QTextStream& operator<< (QTextStream& out, const QList<T>& lst) {
//    for (typename QList<T>::const_iterator ref = lst.begin(); ref != lst.end();
//        ref++)
//        out << *ref; // overloaded <<
//    return out;
//}








// 作者和顾客人名的开头索引
//list<Author> catalog['Z' + 1];
//list<Patron> people['Z' + 1];

//ostream& Author::printAuthor(ostream& out) const {
//    out << name << endl;
//    list<Book>::const_iterator ref = books.begin();
//    for (; ref != books.end(); ref++)
//        out << *ref; // overloaded <<
//    return out;
//}
//ostream& Book::printBook(ostream& out) const {
//    out << "* " << title;
//    if (patron != 0)
//        out << " - checked out to " << patron->name; // overloaded <<
//    out << endl;
//    return out;
//}
//ostream& Patron::printPatron(ostream& out) const {
//    out << name;
//    if (!books.empty()) {
//        out << " has the following books:\n";
//        list<CheckedOutBook>::const_iterator bk = books.begin();
//        for (; bk != books.end(); bk++)
//            out << "*" << bk->author->name << ","
//            << bk->book->title << endl;
//    }
//    else out << " has no books\n";
//    return out;
//}
//template<class T>
//ostream& operator<< (ostream& out, const list<T>& lst) {
//    for (typename list<T>::const_iterator ref = lst.begin(); ref != lst.end();
//        ref++)
//        out << *ref; // overloaded <<
//    return out;
//}



//QString getString(const QString& msg) {
//    QString input;
//    QTextStream in(stdin);
//    cout << msg.toStdString();
//    in >> input;
//    in.readLine(); // 读取并丢弃换行符
//    return input.toUpper();
//}

//QString books;
// 当前状态
//void status() {
//    int i;

//    QTextStream out(stdout);

//    out << "图书馆有以下书籍:\n\n";
//    for (i = 'A'; i <= 'Z'; i++) {
//        if (!catalog[i].empty()) {   // 该字母开头的可能有多本书
//            QList<Book*> bookList = catalog[i];
//            for (int j = 0; j < bookList.size(); j++) {
//                out << bookList[j]->getTitle() << "\n";
//            }
//        }
//    }

//    out << "\n来图书馆借书的人:\n\n";
//    for (i = 'A'; i <= 'Z'; i++) {
//        if (!people[i].empty()) {
//            QList<Person*> personList = people[i];
//            for (int j = 0; j < personList.size(); j++) {
//                out << personList[j]->getName() << "\n";
//            }
//        }
//    }
//}

//template<class T>
//QTextStream& operator<< (QTextStream& out, const list<T>& lst) {
//    for (typename list<T>::const_iterator ref = lst.begin(); ref != lst.end(); ref++){
//        out << *ref; // overloaded <<
//        books += *ref;
//    }
//    return out;
//}

//void checkOutBook() {
//    Patron patron;  // 借书人
//    Author author;  // 要借的书的作者
//    Book book;      // 要借的书的名
//    Qlist<Author>::iterator authorRef;
//    Qlist<Book>::iterator bookRef;
//    patron.name = getString("请输入借书人的名字: ");
//    while (true) {
//        author.name = getString("请输入作者名: ");
//        // 遍历作者list，找不到说明拼错，找到就退出
//        authorRef = find(catalog[author.name[0].toLatin1()].begin(),
//            catalog[author.name[0].toLatin1()].end(), author);
//        if (authorRef == catalog[author.name[0].toLatin1()].end())
//            cout << "拼错作者名\n";
//        else break;
//    }
//    while (true) {
//        book.title = getString("请输入书名: ");
//        // 遍历书list，找不到说明拼错，找到就退出
//        bookRef = find((*authorRef).books.begin(),
//            (*authorRef).books.end(), book);
//        if (bookRef == (*authorRef).books.end())
//            cout << "拼错书名\n";
//        else break;
//    }
//    // 在该名借书人上，添加借书的书名和作者名
//    list<Patron>::iterator patronRef;
//    // 遍历原有借书人list
//    patronRef = find(people[patron.name[0].toLatin1()].begin(),
//        people[patron.name[0].toLatin1()].end(), patron);
//    CheckedOutBook checkedOutBook(authorRef, bookRef);
//    // 没找到，说明是新顾客，需要先加到列表patronRef中
//    if (patronRef == people[patron.name[0].toLatin1()].end()) {
//        patron.books.push_front(checkedOutBook);
//        people[patron.name[0]].push_front(patron);
//        (*bookRef).patron = &*people[patron.name[0].toLatin1()].begin();
//    }
//    // 找到了，说明是老顾客，直接加到book列表里，书也储存被借的人的信息
//    else {
//        (*patronRef).books.push_front(checkedOutBook);
//        (*bookRef).patron = &*patronRef;
//    }
//}

//    Author newAuthor;
//    Book newBook;

//    // 使用 QInputDialog 获取用户输入
//    newAuthor.setName(QInputDialog::getText(this, "Input", "Enter author's name:"));
//    newBook.setTitle(QInputDialog::getText(this, "Input", "Enter the title of the book:"));

//    // 在原有作者中，以新作者名字开头首字母作为起始点进行迭代，查找有没有出现过
//    auto oldAuthor = std::find(catalog[newAuthor.getName()[0]].begin(),
//                               catalog[newAuthor.getName()[0]].end(), newAuthor);

//    // 新的作者出现
//    if (oldAuthor == catalog[newAuthor.getName()[0]].end()) {
//        newAuthor.addBook(newBook);
//        catalog[newAuthor.getName()[0]].push_front(newAuthor);
//    } else {
//        (*oldAuthor).addBook(newBook);
//    }
//void returnBook() {
//    Patron patron;
//    Book book;
//    Author author;
//    list<Patron>::iterator patronRef;
//    list<Book>::iterator bookRef;
//    list<Author>::iterator authorRef;
//    while (true) {
//        patron.name = getString("请输入要归还书的顾客: ");
//        patronRef = find(people[patron.name[0].toLatin1()].begin(),
//            people[patron.name[0].toLatin1()].end(), patron);
//        if (patronRef == people[patron.name[0].toLatin1()].end())
//            cout << "顾客名拼写错误\n";
//        else break;
//    }
//    while (true) {
//        author.name = getString("请输入要归还的书的作者:");
//        authorRef = find(catalog[author.name[0].toLatin1()].begin(),
//            catalog[author.name[0].toLatin1()].end(), author);
//        if (authorRef == catalog[author.name[0].toLatin1()].end())
//            cout << "作者名拼写错误\n";
//        else break;
//    }
//    while (true) {
//        book.title = getString("请输入要归还的书的书名:");
//        bookRef = find((*authorRef).books.begin(),
//            (*authorRef).books.end(), book);
//        if (bookRef == (*authorRef).books.end())
//            cout << "拼错书名\n";
//        else break;
//    }
//    CheckedOutBook checkedOutBook(authorRef, bookRef);
//    (*bookRef).patron = 0;  // 指向0，说明此时书已归还，没人借此书了
//    (*patronRef).books.remove(checkedOutBook);   // 顾客所指向的，自己的books列表中，将该书删除
//}

//char* getString(const char* msg) {
//    char s[82], i, * destin;
//    cout << msg;
//    cin.get(s, 80);
//    while (cin.get(s[81]) && s[81] != '\n'); // discard overflowing
//    destin = new char[strlen(s) + 1];      	 // characters;
//    for (i = 0; destin[i] = toupper(s[i]); i++);
//    return destin;
//}
